package com.jweb.framework.security.crypto.cipher.symmetric;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.jweb.framework.security.crypto.common.EAlgorithm;
import com.jweb.framework.security.crypto.common.ECipherMode;

/**
 * 修改人： Thomas  修改内容：新增 类说明：
 */
public class DefaultSymCipherer implements SymCipherer {

	protected EAlgorithm keyAlgorithm = EAlgorithm.DES;
	protected EAlgorithm cipherAlgorithm = EAlgorithm.DES_CBC_PKCS5Padding;
	protected ECipherMode mode;
	
	public DefaultSymCipherer(){
		
	}
	
	public DefaultSymCipherer(ECipherMode mode) {
		this.mode = mode ;
	}

	public byte[] encrypt(byte[] byte1, byte[] byte2, byte[] byte3) {

		try {
			/**
			 * IvParameterSpec
			 * 此类指定一个初始化向量（IV）。使用IV的例子是反馈模式中的密码。如，CBC模式中的DES和使用OAEP编码操作的RSA密码。
			 */
			IvParameterSpec ivParameterSpec = new IvParameterSpec(byte2);
			/**
			 * SecretKeySpec 此类以与provider无关的方式指定一个密钥
			 * 可以使用此类来根据一个字节数组构造一个SecretKey
			 * ，而无须通过一个(基于provider的)SecretKeyFactory.
			 * 此类仅对能表示为一个字节数组并且没有任何与之相关联的钥参数的原始密码有用，如，DES或者Triple DES密钥。
			 * 
			 * SecretKeySpec(byte[] key, String algorithm)：根据给定的字节数组构造一个密钥。
			 */
			SecretKeySpec secretKeySpec = new SecretKeySpec(byte1,
					this.keyAlgorithm.toString());

			/**
			 * Cipher 此类为加密和解密提供密码功能 。
			 */
			Cipher cipher = Cipher.getInstance(this.cipherAlgorithm.toString());
			
			int num = mode.ordinal() ;
			
			switch (num) {
				case 0:
					/**
					 * init(int opmode , --此 Cipher
					 * 的操作模式（为以下之一：ENCRYPT_MODE、DECRYPT_MODE、WRAP_MODE 或
					 * UNWRAP_MODE） Key key , --加密密钥 AlgorithmParameters params)
					 * --算法参数 用密钥和一组算法参数初始化此Cipher.
					 */
					cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
					break;
				case 1:
					cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
					break;
				default:
					throw new SymmetricEncryptionException(
							"error encrypting/decrypting message: invalid mode;mode = "
									+ this.mode);
			}

			/**
			 * public final byte[] doFinal(byte[] input)
			 * 按单部分操作加密或解密数据，或者结束一个多部分操作。数据将被加密或解密。
			 */
			return cipher.doFinal(byte3);
		} catch (Exception e) {
			throw new SymmetricEncryptionException(
					"error encrypting/decrypting message; mode = " + this.mode,
					e);
		}

	}

	public void setKeyAlgorithm(EAlgorithm ealgorithm) {
		this.keyAlgorithm = ealgorithm;
	}

	public void setCipherAlgorithm(EAlgorithm ealgorithm) {
		this.cipherAlgorithm = ealgorithm;
	}

	public void setMode(ECipherMode ecipherMode) {
		this.mode = ecipherMode;
	}

}
